package com.example.tree.heap;

import java.util.Arrays;
import java.util.PriorityQueue;
import java.util.Queue;

/**
 * 我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。
 * （这里，平面上两点之间的距离是欧几里德距离。）
 * <p>
 * 你可以按任何顺序返回答案。除了点坐标的顺序之外，答案确保是唯一的。
 * <p>
 * 示例 1：
 * <p>
 * 输入：points = [[1,3],[-2,2]], K = 1
 * 输出：[[-2,2]]
 * 解释：
 * (1, 3) 和原点之间的距离为 sqrt(10)，
 * (-2, 2) 和原点之间的距离为 sqrt(8)，
 * 由于 sqrt(8) < sqrt(10)，(-2, 2) 离原点更近。
 * 我们只需要距离原点最近的 K = 1 个点，所以答案就是 [[-2,2]]。
 * <p>
 * 示例 2：
 * <p>
 * 输入：points = [[3,3],[5,-1],[-2,4]], K = 2
 * 输出：[[3,3],[-2,4]]
 * （答案 [[-2,4],[3,3]] 也会被接受。）
 * <p>
 * 提示：
 * <p>
 * 1 <= K <= points.length <= 10000
 * -10000 < points[i][0] < 10000
 * -10000 < points[i][1] < 10000
 */
public class Leetcode973_KClosest {
    public static void main(String[] args) {
        Integer[][] points = {{3,3},{5,-1},{-2,4}};

        Integer[][] res = kClosest(points, 2);

        for (int i = 0; i < res.length; i++) {
            System.out.println(res[i][0] + "," + res[i][1]);
        }

    }

    public static int[][] kClosest2(int[][] points, int K) {
        int N = points.length;
        int[] dists = new int[N];
        for (int i = 0; i < N; ++i)
            dists[i] = distance(points[i]);
        Arrays.sort(dists);
        int distK = dists[K-1];
        int[][] ans = new int[K][2];
        int t = 0;
        for (int i = 0; i < N; ++i)
            if (distance(points[i]) <= distK)
                ans[t++] = points[i];
        return ans;
    }

    public static int distance(int[] p1) {
        return p1[0] * p1[0] + p1[1] * p1[1];
    }

    /**
     * 解法一:最小堆
     * @param points
     * @param k
     * @return
     */
    public static Integer[][] kClosest(Integer[][] points, int k) {

        Queue<Integer[]> minHeap = new PriorityQueue<>(k, (p1, p2) -> (distance(p1) - distance(p2)));

        for (int i = 0; i < points.length; i++) {
            minHeap.offer(points[i]);
        }

        Integer[][] res = new Integer[k][2];
        for (int i = 0; i < k; i++) {
            res[i] = minHeap.poll();
        }
        return  res;

    }

    public static int distance(Integer[] p1) {
        return p1[0] * p1[0] + p1[1] * p1[1];
    }


}
